﻿using GameBasic;
using GameBasic.IO;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;
using System.Collections;
using System;
using System.Collections.Generic;

namespace VCity
{
    public class GameResources : MonoSingleton<GameResources>
    {
        struct TextureLoad
        {
            public string texturePath;
            public UnityWebRequestAsyncOperation op;
        }

        // mesh
        public NetCharCtrl netCharPrefab;
        public Mesh[] characterMeshes;

        //
        AdsData[] adsDatas;
        public Dictionary<string, AdsData> adsDic;

        // texture
        List<TextureLoad> textureLoads;
        public Dictionary<string, Texture2D> textureDic;

        [Header("Config")]
        public bool loadMethod2;
        public bool loadAds;

        /*
        public GameObject[] objs;
        private void OnValidate()
        {
            // get mesh from prefabs
            if (characterMeshes.Length == 0)
            {
                characterMeshes = new Mesh[objs.Length];
                for (int i = 0, length = objs.Length; i < length; i++)
                {
                    var obj = objs[i];
                    characterMeshes[i] = obj.GetComponentInDirectChildren<SkinnedMeshRenderer>().sharedMesh;
                }
            }
        }
        */

        protected override void Awake()
        {
            base.Awake();
            //LoadImage();

            textureDic = new Dictionary<string, Texture2D>();
        }

        private void Update()
        {
            if (loadMethod2)
            {
                if (loadAds)
                {
                    loadAds = false;
                    StartCoroutine(LoadAds2());
                }
            }
            else
            {
                if (loadAds)
                {
                    loadAds = false;
                    LoadAds();
                }

                if (textureLoads != null)
                {
                    for (int i = textureLoads.Count - 1; i >= 0; i--)
                    {
                        var load = textureLoads[i];
                        if (load.op.isDone)
                        {
                            var request = load.op.webRequest;
                            if (request.result == UnityWebRequest.Result.Success)
                            {
                                textureDic[load.texturePath] = DownloadHandlerTexture.GetContent(request);
                                //Debug.Log("Loaded");
                            }
                            //else
                            //{
                            //    Debug.Log($"{request.result}: {load.texturePath}");
                            //}

                            // Clear
                            request.Dispose();
                            textureLoads.RemoveAt(i);
                        }
                    }

                    if (textureLoads.Count == 0)
                    {
                        textureLoads = null;
                        AdsBoardManager.Instance.OnAdsDataUpdate();
                    }
                }
            }
        }

        protected override void OnDestroy()
        {
            base.OnDestroy();

            if (textureLoads != null)
            {
                for (int i = 0, length = textureLoads.Count; i < length; i++)
                    textureLoads[i].op.webRequest.Dispose();
                textureLoads = null;
            }
        }

        #region Ads csv
        void LoadAds()
        {
            string path = Path.Combine(Application.streamingAssetsPath, "Ads.csv");
            StartCoroutine(LoadFromUri(path, request => 
            {
                if (request.result == UnityWebRequest.Result.Success)
                {
                    CsvData csv = new CsvData(request.downloadHandler.text);
                    adsDatas = csv.ParseAll<AdsData>();
                    //Debug.Log(adsDatas[0].text);
                    // Dic
                    adsDic = new Dictionary<string, AdsData>(adsDatas.Length);
                    for (int i = 0, length = adsDatas.Length; i < length; i++)
                    {
                        var a = adsDatas[i];
                        a.Init();
                        adsDatas[i] = a;
                        adsDic[a.id] = a;
                    }

                    // Load texture
                    textureLoads = new List<TextureLoad>(adsDatas.Length);
                    textureDic.Clear();
                    textureDic.EnsureCapacity(adsDatas.Length);
                    for (int i = 0, length = adsDatas.Length; i < length; i++)
                    {
                        string texPath = adsDatas[i].texture;
                        if (!string.IsNullOrEmpty(texPath) && !textureDic.ContainsKey(texPath))
                        {
                            textureDic[texPath] = null;
                            string texUri = IsRemoteUri(texPath) ? texPath : Path.Combine(Application.streamingAssetsPath, texPath);

                            textureLoads.Add(new TextureLoad()
                            {
                                texturePath = texPath,
                                op = UnityWebRequestTexture.GetTexture(texUri).SendWebRequest()
                            });
                        }
                    }
                }

                request.Dispose();
            }));
        }

        IEnumerator LoadAds2()
        {
            string path = Path.Combine(Application.streamingAssetsPath, "Ads.csv");
            using UnityWebRequest webRequest = UnityWebRequest.Get(path);
            yield return webRequest.SendWebRequest();
            // can't load
            if (webRequest.result != UnityWebRequest.Result.Success)
            {
                Debug.Log("Can't load Ads.csv");
                webRequest.Dispose();
                yield break;
            }

            // ads csv
            CsvData csv = new CsvData(webRequest.downloadHandler.text);
            adsDatas = csv.ParseAll<AdsData>();
            //Debug.Log(adsDatas[0].text);
            // Dic
            adsDic = new Dictionary<string, AdsData>(adsDatas.Length);
            for (int i = 0, length = adsDatas.Length; i < length; i++)
            {
                var a = adsDatas[i];
                a.Init();
                adsDatas[i] = a;
                adsDic[a.id] = a;
            }
            // clear
            webRequest.Dispose();

            // load texture
            textureDic.Clear();
            textureDic.EnsureCapacity(adsDatas.Length);
            for (int i = 0, length = adsDatas.Length; i < length; i++)
            {
                string texPath = adsDatas[i].texture;
                if (!string.IsNullOrEmpty(texPath) && !textureDic.ContainsKey(texPath))
                {
                    textureDic[texPath] = null;
                    string texUri = IsRemoteUri(texPath) ? texPath: Path.Combine(Application.streamingAssetsPath, texPath);

                    var texRequest = UnityWebRequestTexture.GetTexture(texUri);
                    yield return texRequest.SendWebRequest();

                    if (texRequest.result == UnityWebRequest.Result.Success)
                    {
                        textureDic[texPath] = DownloadHandlerTexture.GetContent(texRequest);
                    }

                    texRequest.Dispose();
                }
            }

            // inform
            AdsBoardManager.Instance.OnAdsDataUpdate();
        }
        #endregion

        #region Help method
        public static IEnumerator LoadFromUri(string uri, Action<UnityWebRequest> onComplete)
        {
            using UnityWebRequest webRequest = UnityWebRequest.Get(uri);
            // Request and wait for the desired page.
            yield return webRequest.SendWebRequest();

            //string[] pages = uri.Split('/');
            //int page = pages.Length - 1;
            //switch (webRequest.result)
            //{
            //    case UnityWebRequest.Result.ConnectionError:
            //    case UnityWebRequest.Result.DataProcessingError:
            //        Debug.LogError(pages[page] + ": Error: " + webRequest.error);
            //        break;
            //    case UnityWebRequest.Result.ProtocolError:
            //        Debug.LogError(pages[page] + ": HTTP Error: " + webRequest.error);
            //        break;
            //    case UnityWebRequest.Result.Success:
            //        Debug.Log(pages[page] + ":\nReceived: " + webRequest.downloadHandler.text);
            //        break;
            //}

            onComplete(webRequest);
        }

        static IEnumerator LoadTextureFromUri(string uri, Action<UnityWebRequest> onCompelte)
        {
            using UnityWebRequest webRequest = UnityWebRequestTexture.GetTexture(uri);
            // Request and wait for the desired page.
            yield return webRequest.SendWebRequest();
            onCompelte(webRequest);
        }

        public static bool IsRemoteUri(string uri)
        {
            return uri.StartsWith("http");
        }
        #endregion
    }
}